<!-- <!DOCTYPE html> -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "
http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
      <meta charset="utf-8">
      <title>
          数组使用
      </title>
      <link rel="stylesheet" type="text/css" href="common.css"/>
      <style type="text/css">
        .radio-list{ font-size: 16px;text-align: left; }
        .radio-list input{ width: 16px;height: 16px;cursor: pointer; }
        .panel { display: none; }
        .un-detail, .sort-detail, .random-detail { display: none;margin: 20px 0px; }
      </style>
      <script src="lib/syntax_highlighter/brush.js" type="text/javascript"></script>
      <link rel="stylesheet" type="text/css" href="lib/syntax_highlighter/shCore.css" />
      <link rel="stylesheet" type="text/css" href="lib/syntax_highlighter/shThemeDefault.css" />
      <link rel="icon" href="favicon.ico" type="image/x-icon" />
      <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
    </head>
    
    <body>
        <h3>数组用法</h3>
        <div class='btn-list' id="btnCont">
          <button id="uniqueBtn" class="radius-btn">数组去重</button>
          <button id="sortBtn" class="radius-btn">数组排序</button>
          <button id="randomBtn" class="radius-btn">随机数组</button>
        </div>

        <div id="uniquePanel" class="panel">
          <p>数组去重</p>
          <p>原始数组： [4, 2, 5, 5, 8, 12, 43, 7, 2]</p>
          <div class="radio-list">
            <input type="radio" name="unique" data-id="r1"/>
            <label>遍历数组法</label>
            <input type="radio" name="unique" data-id="r2"/>
            <label>对象键值对法</label>
            <input type="radio" name="unique" data-id="r3"/>
            <label>数组下标判断法</label>
            <input type="radio" name="unique" data-id="r4"/>
            <label>排序后相邻去除法</label>
            <input type="radio" name="unique" data-id="r5" checked="checked" />
            <label>优化遍历数组法</label>
          </div>

          <div class="unique-details" id="unDetail">
            <div class="un-detail" id="r1">
              <strong>结果：</strong>
              <p id='r1-res'></p>
              <p>检测浏览器是否支持ECMA5</p>
              <pre class='brush: javascript'>
                // 判断浏览器是否支持indexOf ，indexOf 为ecmaScript5新方法 IE8以下（包括IE8， IE8只支持部分ecma5）不支持
                if (!Array.prototype.indexOf){
                  // 新增indexOf方法
                  Array.prototype.indexOf = function(item){
                    var result = -1, a_item = null;
                    if (this.length == 0){
                      return result;
                    }
                    for(var i = 0, len = this.length; i < len; i++){
                      a_item = this[i];
                      if (a_item === item){
                        result = i;
                        break;
                      }  
                    }
                    return result;
                  }
                }
              </pre>
              <p>普通遍历数组法：</p>
              <pre class='brush: javascript'>
                // 最简单数组去重法
                function unique1(array){
                  var n = []; //一个新的临时数组
                  //遍历当前数组
                  for(var i = 0; i < array.length; i++){
                    //如果当前数组的第i已经保存进了临时数组，那么跳过，
                    //否则把当前项push到临时数组里面
                    if (n.indexOf(array[i]) == -1) n.push(array[i]);
                  }
                  return n;
                }
              </pre>
            </div>
            <div class="un-detail" id="r2">
              <strong>结果：</strong>
              <p id="r2-res"></p>
              <p>对象键值对法：</p>
              <pre class='brush: javascript'>
                // 速度最快， 占空间最多（空间换时间）
                function unique2(array){
                  var n = {}, r = [], len = array.length, val, type;
                    for (var i = 0; i < array.length; i++) {
                        val = array[i];
                        type = typeof val;
                        if (!n[val]) {
                            n[val] = [type];
                            r.push(val);
                        } else if (n[val].indexOf(type) < 0) {
                            n[val].push(type);
                            r.push(val);
                        }
                    }
                    return r;
                }
              </pre>
            </div>
            <div class="un-detail" id="r3">
              <strong>结果：</strong>
              <p id="r3-res"></p>
              <p>数组下标判断法</p>
              <pre class="brush:javascript">
                function unique3(array){
                  var n = [array[0]]; //结果数组
                  //从第二项开始遍历
                  for(var i = 1; i < array.length; i++) {
                    //如果当前数组的第i项在当前数组中第一次出现的位置不是i，
                    //那么表示第i项是重复的，忽略掉。否则存入结果数组
                    if (array.indexOf(array[i]) == i) n.push(array[i]);
                  }
                  return n;
                }
              </pre>
            </div>
            <div class="un-detail" id="r4">
              <strong>结果：</strong>
              <p id="r4-res"></p>
              <p>排序后相邻去除法</p>
              <pre class="brush:javascript">
                // 将相同的值相邻，然后去除
                function unique4(array){
                  array.sort(); 
                  var re=[array[0]];
                  for(var i = 1; i < array.length; i++){
                    if( array[i] !== re[re.length-1])
                    {
                      re.push(array[i]);
                    }
                  }
                  return re;
                }
              </pre>
            </div>
            <div class="un-detail" id="r5">
              <strong>结果：</strong>
              <p id="r5-res"></p>
              <p>优化遍历数组法，代码思路来自：
                <a title="数组快速去重" href="http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/" target="_blank">数组快速去重</a>
              </p>
              <pre class="brush:javascript">
                // 思路：获取没重复的最右一值放入新数组
                function unique5(array){
                  var r = [];
                  for(var i = 0, l = array.length; i < l; i++) {
                    for(var j = i + 1; j < l; j++)
                      if (array[i] === array[j]) j = ++i;
                    r.push(array[i]);
                  }
                  return r;
                }
              </pre>
            </div>
          </div>

        </div>
        
        <div id="sortPanel" class="panel">
          <p>数组排序算法总结：<a href="http://jsdo.it/norahiko/oxIy/fullscreen" alt="jpan">日本人编写的排序动画</a></p>
          <p>原始数组： [5,6,3,4,9,7,8,12,10,11,2,1]</p>
          <div class="radio-list">
            <input type="radio" name="sort" data-id="s1"/>
            <label>插入排序</label>
            <input type="radio" name="sort" data-id="s2"/>
            <label>二分插入排序</label>
            <input type="radio" name="sort" data-id="s3"/>
            <label>希尔排序</label>
            <input type="radio" name="sort" data-id="s4"/>
            <label>冒泡排序</label>
            <input type="radio" name="sort" data-id="s5"/>
            <label>改进冒泡排序</label>
            <input type="radio" name="sort" checked="checked" data-id="s6" />
            <label>快速排序</label>
            <input type="radio" name="sort" data-id="s7"/>
            <label>选择排序</label>
            <input type="radio" name="sort" data-id="s8"/>
            <label>堆排序</label>
            <input type="radio" name="sort" data-id="s9"/>
            <label>归并排序</label>
          </div>

          <div class="sort-details" id="sortDetail">
            <div class="sort-detail" id="s1">
              <strong>结果：</strong>
              <p id="s1-res"></p>
              <p>原理图：</p>
              <img title="插入排序原理图" alt="插入排序原理图" src="images/sort1.png"/>
              <p>插入排序算法</p>
              <pre class="brush:javascript">
                // 插入排序 从下标1开始每增1项排序一次，越往后遍历次数越多
                function sort1(array) {
                  var len = array.length,
                      i, j, tmp, result;
                  
                  // 设置数组副本
                  result = array.slice(0);
                  for(i=1; i < len; i++){
                    tmp = result[i];
                    j = i - 1;
                    while(j>=0 && tmp < result[j]){
                      result[j+1] = result[j];
                      j--;
                    }
                    result[j+1] = tmp;
                  }
                  return result;
                }
              </pre>
            </div>
            <div class="sort-detail" id="s2">
              <strong>结果：</strong>
              <p id="s2-res"></p>
              <p>原理图：</p>
              <img alt="二分插入排序原理图" src="images/sort2.jpg" title="二分插入排序原理图"/>
              <p>二分插入排序</p>
              <pre class="brush:javascript">
                // 先在有序区通过二分查找的方法找到移动元素的起始位置，然后通过这个起始位置将后面所有的元素后移
                function sort2(array) {
                  var len = array.length,
                      i, j, tmp, low, high, mid, result;
                  // 赋予数组副本
                  result = array.slice(0);
                  for(i = 1; i < len; i++){
                    tmp = result[i];
                    low = 0;
                    high = i - 1;
                    while(low <= high){
                      mid = parseInt((low + high)/2, 10);
                      if(tmp < result[mid]) high = mid - 1;
                      else low = mid + 1;
                    }
                    for(j = i - 1; j >= high+1; j--){
                      result[j+1] = result[j];            
                    }
                    result[j+1] = tmp;
                  }
                  return result;
                }
              </pre>
            </div>
            <div class="sort-detail" id="s3">
              <strong>结果：</strong>
              <p id="s3-res"></p>
              <p>原理图：</p>
              <img alt="希尔排序原理图" src="images/sort3.jpg" title="希尔排序原理图"/>
              <p>希尔排序</p>
              <pre class="brush:javascript">
                // 希尔排序：先将整个待排序记录序列分割成若干个子序列，在在序列内分别进行直接插入排序，待整个序列基本有序时，再对全体记录进行一次直接插入排序
                function sort3(array){
                  var len = array.length, gap = parseInt(len/2), 
                      i, j, tmp, result;
                  // 复制数组
                  result = array.slice(0);
                  while(gap > 0){
                    for(i = gap; i < len; i++){
                      tmp = result[i];
                      j = i - gap;
                      while(j>=0 && tmp < result[j]){
                        result[j + gap] = result[j];
                        j = j - gap;
                      }
                      result[j + gap] = tmp;
                    }
                    gap = parseInt(gap/2);
                  }
                  return result;
                }
              </pre>
            </div>
            <div class="sort-detail" id="s4">
              <strong>结果：</strong>
              <p id="s4-res"></p>
              <p>原理图：</p>
              <img alt="冒泡排序原理图" src="images/sort4.png" title="冒泡排序原理图"/>
              <p>冒泡排序</p>
              <pre class="brush:javascript">
                // 冒泡排序 每次将最小元素推至最前
                function sort4(array) {
                  var len = array.length,
                  i, j, tmp, result;
                  result = array.slice(0);
                  for (i = 0; i < len; i++) {
                    for (j = len - 1; j > i; j--) {
                      if (result[j] < result[j - 1]) {
                        tmp = result[j - 1];
                        result[j - 1] = result[j];
                        result[j] = tmp;
                      }
                    }
                  }
                  return result;
                }
              </pre>
            </div>
            <div class="sort-detail" id="s5">
              <strong>结果：</strong>
              <p id="s5-res"></p>
              <p>原理图：</p>
              <img alt="改进冒泡排序原理图" src="images/sort5.jpg" title="冒泡排序原理图"/>
              <p>改进冒泡排序</p>
              <pre class="brush:javascript">
                // 如果在某次的排序中没有出现交换的情况，那么说明在无序的元素现在已经是有序了，就可以直接返回了。
                function sort5(array) {
                  var len = array.length,
                  i, j, tmp, exchange, result;

                  result = array.slice(0);
                  for (i = 0; i < len; i++) {
                    exchange = 0;
                    for (j = len - 1; j > i; j--) {
                      if (result[j] < result[j - 1]) {
                        tmp = result[j];
                        result[j] = result[j - 1];
                        result[j - 1] = tmp;
                        exchange = 1;
                      }
                    }
                    if (!exchange) return result;
                  }
                  return result;
                }
              </pre>
            </div>
            <div class="sort-detail" id="s6">
              <strong>结果：</strong>
              <p id="s6-res"></p>
              <p>原理图：</p>
              <img alt="快速排序原理图" src="images/sort6.jpg" title="快速排序原理图"/>
              <p>快速排序</p>
              <pre class="brush:javascript">
                //（1）在数据集之中，选择一个元素作为"基准"（pivot）。
                //（2）所有小于"基准"的元素，都移到"基准"的左边；所有大于"基准"的元素，都移到"基准"的右边。
                //（3）对"基准"左边和右边的两个子集，不断重复第一步和第二步，直到所有子集只剩下一个元素为止。
                function sort6(array) {
                  var tmp_array = array.slice(0), result,
                  quickSort = function(arr) {
                　　if (arr.length <= 1) { return arr; }
                　　var pivotIndex = Math.floor(arr.length / 2);
                　　var pivot = arr.splice(pivotIndex, 1)[0];
                　　var left = [];
                　　var right = [];
                　　for (var i = 0; i < arr.length; i++){
                　　　　if (arr[i] < pivot) {
                　　　　　　left.push(arr[i]);
                　　　　} else {
                　　　　　　right.push(arr[i]);
                　　　　}
                　　}
                　　return quickSort(left).concat([pivot], quickSort(right));
                  };
                  result = quickSort(tmp_array);
                  return result;
                }
              </pre>
            </div>
            <div class="sort-detail" id="s7">
              <strong>结果：</strong>
              <p id="s7-res"></p>
              <p>原理图：</p>
              <img alt="选择排序原理图" src="images/sort7_1.jpg" title="选择排序原理图"/>
              <p>选择排序</p>
              <pre class="brush:javascript">
                // 在无序区中选出最小的元素，然后将它和无序区的第一个元素交换位置。
                // 原理跟冒泡排序一样，算是冒泡的衍生版本
                function sort7(array) {
                  var len = array.length,
                  i, j, k, tmp, result;

                  result = array.slice(0);
                  for (i = 0; i < len; i++) {
                    k = i;
                    for (j = i + 1; j < len; j++) {
                      if (result[j] < result[k]) k = j;
                    }
                    if (k != i) {
                      tmp = result[k];
                      result[k] = result[i];
                      result[i] = tmp;
                    }
                  }
                  return result;
                }
              </pre>
            </div>
            <div class="sort-detail" id="s8">
              <strong>结果：</strong>
              <p id="s8-res"></p>
              <p>堆排序原理太复杂，一张图表达不了：详情请看：
                <a alt="堆排序" title="堆排序" href="http://www.cnblogs.com/zabery/archive/2011/07/26/2117103.html" target="_blank">堆排序原理分析</a>
              </p>
              <div>
                <strong>1.调整二叉树，形成大根堆(子节点都比父节点小)。</strong>
                <p><img alt="堆排序1" src="images/sort8_1.png" title="堆排序1" /></p>
              </div>
              <div>
                <strong>2.交换堆第一元素跟最后元素位置，最后元素弹出堆。然后继续回到1，调整堆。</strong>
                <p><img alt="堆排序2" src="images/sort8_2.png" title="堆排序2" /></p>
              </div>
              <div>
                <strong>3.重复2， 当所有节点弹出堆后；弹出的节点值就是有序的了。</strong>
                <p><img alt="堆排序3" src="images/sort8_3.png" title="堆排序3" /></p>
              </div>
              <p>堆排序</p>
              <pre class="brush:javascript">
                // 1) 初始堆：将原始数组调整成大根堆的方法——筛选算法:子节点都比父节点小
                // 2) 堆排序： 每次将堆顶元素与数组最后面的且没有被置换的元素互换。
                // 参考代码： http://bubkoo.com/2014/01/14/sort-algorithm/heap-sort/
                function sort8(array) {
                  var result = array.slice(0);

                  function swap(array, i, j) {
                    var temp = array[i];
                    array[i] = array[j];
                    array[j] = temp;
                  }

                  function maxHeapify(array, index, heapSize) {
                    var iMax, iLeft, iRight;
                    while (true) {
                      iMax = index;
                      iLeft = 2 * index + 1;
                      iRight = 2 * (index + 1);

                      if (iLeft < heapSize && array[index] < array[iLeft]) {
                        iMax = iLeft;
                      }

                      if (iRight < heapSize && array[iMax] < array[iRight]) {
                        iMax = iRight;
                      }

                      if (iMax != index) {
                        swap(array, iMax, index);
                        index = iMax;
                      } else {
                        break;
                      }
                    }
                  }

                  function buildMaxHeap(array) {
                    var i, iParent = Math.floor(array.length / 2) - 1;

                    for (i = iParent; i >= 0; i--) {
                      maxHeapify(array, i, array.length);
                    }
                  }

                  function sort(array) {
                    buildMaxHeap(array);

                    for (var i = array.length - 1; i > 0; i--) {
                      swap(array, 0, i);
                      maxHeapify(array, 0, i);
                    }
                    return array;
                  }

                  return sort(result);
                }
              </pre>
            </div>
            <div class="sort-detail" id="s9">
              <strong>结果：</strong>
              <p id="s9-res"></p>
              <p>原理图：</p>
              <img alt="归并排序原理图" src="images/sort9.jpg" title="归并排序原理图"/>
              <p>归并排序</p>
              <pre class="brush:javascript">
                // 合并排序：将无序的数组 拆成N部分进行有序处理，然后合并；
                // 参考代码： https://gist.github.com/paullewis/1982121
                function sort9(array) {
                  var result = array.slice(0);

                  // 递归调用合并函数
                  function sort(array) {
                    var length = array.length,
                    mid = Math.floor(length * 0.5),
                    left = array.slice(0, mid),
                    right = array.slice(mid, length);

                    if (length === 1) {
                      return array;
                    }
                    return merge(sort(left), sort(right));
                  }

                  // 合并 两有序的数组
                  function merge(left, right) {
                    var result = [];

                    while (left.length || right.length) {

                      if (left.length && right.length) {

                        if (left[0] < right[0]) {
                          result.push(left.shift());
                        } else {
                          result.push(right.shift());
                        }

                      } else if (left.length) {
                        result.push(left.shift());
                      } else {
                        result.push(right.shift());
                      }
                    }
                    return result;
                  }

                  return sort(result);
                }
              </pre>
            </div>
          </div>

        </div>

        <div id="randomPanel" class="panel">
          <p>显示随机数组</p>
          <p>原始数组： [8,2, 3, 55, 12, 20, 16, 18, 15, 20, 11, 7]</p>
          <div class="radio-list">
            <input type="radio" name="random" data-id="ran1" checked="checked"/>
            <label>从数组中随机获取N个不重复的值</label>
            <input type="radio" name="random" data-id="ran2"/>
            <label>打乱数组顺序，要求数组中的每个元素都不能停留在原来的位置</label>
            <input type="radio" name="random" data-id="ran3"/>
            <label>从指定范围内，随机获取N个值的数组</label>
          </div>

          <div class="random-details" id="randomDetail">
            <div class="random-detail" id="ran1">
              <strong>结果：</strong>
              <p id="ran1-res"></p>
              
              <p>对应代码：</p>
              <pre class="brush:javascript">
                // 随机从数组中获取 N个不重复的值, 默认从数组取一个值
                function ran1(array, n){
                  var _result = [], _index = 0, _arrayTemp;
                  // 防止原数组被改变
                  _arryTemp = array.slice(0); 
                  if (array == null || array.length == 0 || array.length < n){
                    return _result;
                  }
                  // 随机获取一个值
                  if (n == null){
                    _index = Math.floor(Math.random() * array.length);
                    _result.push(array[_index]);
                  }else{
                    // 随机获取N个值
                    for (var i = 0; i < n; i++){
                      _index = Math.floor(Math.random() * _arrayTemp.length);
                      _result.push(_arrayTemp[_index]);
                      // 删除该元素
                      _arrayTemp.splice(_index, 1);
                    }
                  }
                  return _result;
                }
              </pre>
            </div>

            <div class="random-detail" id="ran2">
              <strong>结果：</strong>
              <p id="ran2-res"></p>

              <p>对应代码：</p>
              <pre class="brush:javascript">
                // 随机打乱数组，使数组内元素与原来位置完全不同
                function ran2(array){
                  var array_tmp = [], i , j, len, new_a = [], a_obj;
                  
                  // 添加数组原位置标志位
                  for (i = 0, len = array.length; i < len; i++) {
                    a_obj = {
                      'key': i,
                      'val': array[i]
                    };
                    array_tmp.push(a_obj);
                  }

                  for (i = 0, len = array.length; i < len; i++) {
                    j = ranCount(array_tmp.length);
                    // 如下标位置与原值重复，重新随机
                    while ( i === array_tmp[j].key ) {
                      j = ranCount(array_tmp.length);
                    }
                    new_a.push( array_tmp[j].val );
                    // 删除数组
                    array_tmp.splice(j,1);
                  }

                  // 获得给定数字的随机数, 出错返回-1
                  function ranCount(n){
                    var result = parseInt(n, 10);
                    if ( isNaN(result) ) {
                      result = -1;
                    }
                    result = Math.floor(Math.random() * result)
                    return result;
                  }

                  return new_a;
                  }
              </pre>
            </div>

            <div class="random-detail" id="ran3">
              <strong>结果：</strong>
              <p id="ran3-res"></p>

              <p>对应代码：</p>
              <pre class="brush:javascript">
                // 从指定范围内(暂定为100以内)，随机获取N（暂定为10）个值的数组
                function ran3(){
                  var result = [], SCOPE_NO = 100, COUNT = 10;

                  result = getRandomNo(SCOPE_NO, COUNT);
                  function getRandomNo(scope_no, count){
                    var i, s_n, ran_n, _result = [];
                    
                    s_n = parseInt(scope_no, 10);
                    for (i = 0; i < count; i++) {
                      ran_n = Math.floor(Math.random() * s_n);
                      _result.push(ran_n);
                    }
                    return _result;
                  }

                  return result;
                }
              </pre>
            </div>
          </div>
        </div>

        <script type="text/javascript" src="utils/base.js"></script>
        <script>
          // @global xq 全局变量命名空间
          var xq = {};
          // 测试以上函数 方便演示代码， 添加代码高亮插件
          xq.t_array = [4, 2, 5, 5, 8, 12, 43, 7, 2];
          xq.unique_fns = {};
          xq.sort_fns = {};
          xq.random_fns = {};
          xq.sort_array = [5,6,3,4,9,7,8,12,10,11,2,1];

          init();

          function init(){
            var unique_btn, sort_btn, unique_panel, sort_panel,unique_radios, sort_radios;

            unique_btn = document.getElementById('uniqueBtn');
            sort_btn = document.getElementById('sortBtn');
            random_btn = document.getElementById('randomBtn');

            unique_btn.onclick = showUniquePanel;
            sort_btn.onclick = showSortPanel;
            random_btn.onclick = showRandomPanel;

            // raido 事件处理
            unique_radios = document.getElementsByName('unique');
            sort_radios = document.getElementsByName('sort');
            random_radios = document.getElementsByName('random');

            // 初始化 数组函数
            initArrayFns();
            // 初始化 数组去重radio事件
            initRadios(unique_radios, 'un-detail');
            // 初始化 数组排序radio事件
            initRadios(sort_radios, 'sort-detail');
            // 初始化 随机数组radio事件
            initRadios(random_radios, 'random-detail');

            // 代码高亮显示
            SyntaxHighlighter.config.clipboardSwf = 'http://static.oschina.net/js/syntax-highlighter-2.1.382/scripts/clipboard.swf';
            SyntaxHighlighter.all();

            // 根据URL判断进入哪个Demo
            gotoDemo();
          }

          // 根据URL判断进入哪个Demo: array.html#t=unique&d=r1
          function gotoDemo(){
            var t_url, panel_type, panel_detail;
            // 根据URL现实对应内容
            t_url = window.location.hash.replace('#', '');
            t_url = !!t_url ? t_url.split('&') : '';
            if (t_url && t_url.length > 0) {
              panel_type = t_url[0].split('=')[1];
              panel_detail = t_url[1].split('=')[1];
              if (panel_type === 'sort') {
                // 显示数组排序 demo
                showSortPanel();
                // 触发对应radio 
                triggerRadio('sort', panel_detail);
                // 默认去重radio触发
                triggerRadio('unique', 'r5');
                // 默认显示 获取N个值
                triggerRadio('random', 'ran1');
              }else if(panel_type === 'unique') {
                // 显示数组去重 demo
                showUniquePanel();
                // 触发对应radio 
                triggerRadio('unique', panel_detail);
                // 默认排序radio触发
                triggerRadio('sort', 's6');
                // 默认显示 获取N个值
                triggerRadio('random', 'ran1');
              }else if(panel_type === 'random') {
                // 显示随机数组 demo
                showRandomPanel();
                // 触发对应radio 
                triggerRadio('random', panel_detail);
                // 默认去重radio触发
                triggerRadio('unique', 'r5');
                // 默认排序radio触发
                triggerRadio('sort', 's6');
              }
            }else{
              // 默认显示数组去重 demo
              showUniquePanel();
              // 默认显示优化遍历数组法
              showDetail('r5', 'un-detail');
              // 默认显示 快速排序
              showDetail('s6', 'sort-detail');
              // 默认显示 获取N个值
              showDetail('ran1', 'random-detail');
            }
          }
          // 初始化 算法函数
          function initArrayFns(){
            // 初始化去重函数
            xq.unique_fns['r1'] = unique1;
            xq.unique_fns['r2'] = unique2;
            xq.unique_fns['r3'] = unique3;
            xq.unique_fns['r4'] = unique4;
            xq.unique_fns['r5'] = unique5;
            // 初始化排序函数
            xq.sort_fns['s1'] = sort1;
            xq.sort_fns['s2'] = sort2;
            xq.sort_fns['s3'] = sort3;
            xq.sort_fns['s4'] = sort4;
            xq.sort_fns['s5'] = sort5;
            xq.sort_fns['s6'] = sort6;
            xq.sort_fns['s7'] = sort7;
            xq.sort_fns['s8'] = sort8;
            xq.sort_fns['s9'] = sort9;
            // 初始化随机函数
            xq.random_fns['ran1'] = ran1;
            xq.random_fns['ran2'] = ran2;
            xq.random_fns['ran3'] = ran3;
          }

          function showUniquePanel(){
            showPanel('uniquePanel');
          }
          function showSortPanel(){
            showPanel('sortPanel');
          }
          function showRandomPanel(){
            showPanel('randomPanel');
          }

          function triggerRadio(type, r_id){
            var radios, i , len, radio;
            // 获得radios列表
            radios = document.getElementsByName(type);
            for (i = 0, len = radios.length; i < len; i++) {
              radio = radios[i];
              if (radio.getAttribute('data-id') === r_id) {
                radio.click();
                break;
              }
            }
          }
          function hideAllPanel(){
            var panel_list, i, len, p_item;
            panel_list = document.getElementsByClassName('panel');
            for (i = 0, len = panel_list.length; i < len; i++) {
              p_item = panel_list[i];
              p_item.style.display = 'none';
            }
          }
          function showPanel(p_id){
            var p_item; 
            hideAllPanel();
            p_item = document.getElementById(p_id);
            p_item.style.display = 'block';
          }

          // 初始化 radio按钮事件
          function initRadios(btn_list, p_class){
            var i, len, btn, b_id;

            for (i = 0, len = btn_list.length; i < len; i++) {
              btn = btn_list[i];
              btn.onclick = function(){
                var b_id = this.getAttribute('data-id');
                showDetail(b_id, p_class);
              }
            }
          }
          // 隐藏指定类型的所有详情面板
          function hideAllDetail(detail_list){
            var i , len, detail;
            if (!detail_list || detail_list.length == 0) {
              return false;
            }
            for (i = 0, len = detail_list.length; i < len; i++) {
              detail = detail_list[i];
              detail.style.display = 'none';
            }
          }
          // 显示某一详情面板
          function showDetail(u_id, p_class){
            var detail_list, show_detail, result, result_panel;
            if (!u_id) {
              return false;
            }
            detail_list = document.getElementsByClassName(p_class);
            show_detail = document.getElementById(u_id);
            hideAllDetail(detail_list);
            show_detail.style.display = 'block';
            if (p_class === 'un-detail' && (typeof xq.unique_fns[u_id]) === 'function') {
              // 执行对应函数
              result = xq.unique_fns[u_id](xq.t_array);
              // 结果显示在对应面板中
              result_panel = document.getElementById(u_id + '-res');
              result_panel.innerHTML = '';
              result_panel.appendChild(document.createTextNode(result));
            } else if (p_class === 'sort-detail' && (typeof xq.sort_fns[u_id]) === 'function'){
              // 执行对应函数
              result = xq.sort_fns[u_id](xq.sort_array);
              // 结果显示在对应面板中
              result_panel = document.getElementById(u_id + '-res');
              result_panel.innerHTML = '';
              result_panel.appendChild(document.createTextNode(result));
            } else if (p_class === 'random-detail' && (typeof xq.random_fns[u_id]) === 'function'){
              // 执行对应函数
              result = xq.random_fns[u_id](xq.sort_array);
              // 结果显示在对应面板中
              result_panel = document.getElementById(u_id + '-res');
              result_panel.innerHTML = '';
              result_panel.appendChild(document.createTextNode(result));
            }
          }

          // 最简单数组去重法
          function unique1(array){
            var n = []; //一个新的临时数组
            //遍历当前数组
            for(var i = 0; i < array.length; i++){
              //如果当前数组的第i已经保存进了临时数组，那么跳过，
              //否则把当前项push到临时数组里面
              if (n.indexOf(array[i]) == -1) n.push(array[i]);
            }
            return n;
          }

          // 速度最快， 占空间最多（空间换时间）
          function unique2(array){
            var n = {}, r = [], len = array.length, val, type;
              for (var i = 0; i < array.length; i++) {
                  val = array[i];
                  type = typeof val;
                  if (!n[val]) {
                      n[val] = [type];
                      r.push(val);
                  } else if (n[val].indexOf(type) < 0) {
                      n[val].push(type);
                      r.push(val);
                  }
              }
              return r;
          }

          function unique3(array){
            var n = [array[0]]; //结果数组
            //从第二项开始遍历
            for(var i = 1; i < array.length; i++) {
              //如果当前数组的第i项在当前数组中第一次出现的位置不是i，
              //那么表示第i项是重复的，忽略掉。否则存入结果数组
              if (array.indexOf(array[i]) == i) n.push(array[i]);
            }
            return n;
          }

          // 将相同的值相邻，然后去除
          function unique4(array){
            array.sort(); 
            var re=[array[0]];
            for(var i = 1; i < array.length; i++){
              if( array[i] !== re[re.length-1])
              {
                re.push(array[i]);
              }
            }
            return re;
          }
          // 思路：获取没重复的最右一值放入新数组
          function unique5(array){
            var r = [];
            for(var i = 0, l = array.length; i < l; i++) {
              for(var j = i + 1; j < l; j++)
                if (array[i] === array[j]) j = ++i; 
              r.push(array[i]);
            }
            return r;
          }

          // 插入排序 从下标1开始每增1项排序一次，越往后遍历次数越多
          function sort1(array) {
            var len = array.length,
                i, j, tmp, result;

            // 赋予数组副本
            result = array.slice(0);
            for(i=1; i<len; i++){
              tmp = result[i];
              j = i - 1;
              while(j>=0 && tmp < result[j]){
                result[j+1] = result[j];
                j--;
              }
              result[j+1] = tmp;
            }
            return result;
          }
          // 先在有序区通过二分查找的方法找到移动元素的起始位置，然后通过这个起始位置将后面所有的元素后移
          // 关于二分查找排序，该贴子的图比较易懂http://www.cnblogs.com/liuling/p/2013-7-24-01.html
          function sort2(array) {
            var len = array.length,
                i, j, tmp, low, high, mid, result;
            // 赋予数组副本
            result = array.slice(0);
            for(i = 1; i < len; i++){
              tmp = result[i];
              low = 0;
              high = i - 1;
              while(low <= high){
                mid = parseInt((low + high)/2, 10);
                if(tmp < result[mid]) high = mid - 1;
                else low = mid + 1;
              }
              for(j = i - 1; j >= high+1; j--){
                result[j+1] = result[j];            
              }
              result[j+1] = tmp;
            }
            return result;
          }
          // 希尔排序：
          function sort3(array){
            var len = array.length, gap = parseInt(len/2), 
                i, j, tmp, result;
            // 复制数组
            result = array.slice(0);
            while(gap > 0){
              for(i = gap; i < len; i++){
                tmp = result[i];
                j = i - gap;
                while(j>=0 && tmp < result[j]){
                  result[j + gap] = result[j];
                  j = j - gap;
                }
                result[j + gap] = tmp;
              }
              gap = parseInt(gap/2);
            }
            return result;
          }

          // 冒泡排序 每次将最小元素推至最前
          function sort4(array) {
            var len = array.length,
            i, j, tmp, result;
            result = array.slice(0);
            for (i = 0; i < len; i++) {
              for (j = len - 1; j > i; j--) {
                if (result[j] < result[j - 1]) {
                  tmp = result[j - 1];
                  result[j - 1] = result[j];
                  result[j] = tmp;
                }
              }
            }
            return result;
          }
          
          // 如果在某次的排序中没有出现交换的情况，那么说明在无序的元素现在已经是有序了，就可以直接返回了。
          function sort5(array) {
            var len = array.length,
            i, j, tmp, exchange, result;

            result = array.slice(0);
            for (i = 0; i < len; i++) {
              exchange = 0;
              for (j = len - 1; j > i; j--) {
                if (result[j] < result[j - 1]) {
                  tmp = result[j];
                  result[j] = result[j - 1];
                  result[j - 1] = tmp;
                  exchange = 1;
                }
              }
              if (!exchange) return result;
            }
            return result;
          }

          //（1）在数据集之中，选择一个元素作为"基准"（pivot）。
          //（2）所有小于"基准"的元素，都移到"基准"的左边；所有大于"基准"的元素，都移到"基准"的右边。
          //（3）对"基准"左边和右边的两个子集，不断重复第一步和第二步，直到所有子集只剩下一个元素为止。
          function sort6(array) {
            var tmp_array = array.slice(0), result, quickSort;

            quickSort = function(arr) {　　
              if (arr.length <= 1) {
                return arr;
              }　　
              var pivotIndex = Math.floor(arr.length / 2);　　
              var pivot = arr.splice(pivotIndex, 1)[0];　　
              var left = [];　　
              var right = [];　　
              for (var i = 0; i < arr.length; i++) {　　　　
                if (arr[i] < pivot) {　　　　　　
                  left.push(arr[i]);　　　　
                } else {　　　　　　
                  right.push(arr[i]);　　　　
                }　　
              }　　
              return quickSort(left).concat([pivot], quickSort(right));
            };

            result = quickSort(tmp_array);
            return result;
          }

          // 在无序区中选出最小的元素，然后将它和无序区的第一个元素交换位置。
          // 冒泡排序的衍生版本
          function sort7(array) {
            var len = array.length,
            i, j, k, tmp, result;

            result = array.slice(0);
            for (i = 0; i < len; i++) {
              k = i;
              for (j = i + 1; j < len; j++) {
                if (result[j] < result[k]) k = j;
              }
              if (k != i) {
                tmp = result[k];
                result[k] = result[i];
                result[i] = tmp;
              }
            }
            return result;
          }

          // 1) 初始堆：将原始数组调整成大根堆的方法——筛选算法:子节点都比父节点小
          // 2) 堆排序： 每次将堆顶元素与数组最后面的且没有被置换的元素互换。
          // 参考代码： http://bubkoo.com/2014/01/14/sort-algorithm/heap-sort/
          function sort8(array) {
            var result = array.slice(0);

            function swap(array, i, j) {
              var temp = array[i];
              array[i] = array[j];
              array[j] = temp;
            }

            function maxHeapify(array, index, heapSize) {
              var iMax,
                iLeft,
                iRight;
              while (true) {
                iMax = index;
                iLeft = 2 * index + 1;
                iRight = 2 * (index + 1);

                if (iLeft < heapSize && array[index] < array[iLeft]) {
                  iMax = iLeft;
                }

                if (iRight < heapSize && array[iMax] < array[iRight]) {
                  iMax = iRight;
                }

                if (iMax != index) {
                  swap(array, iMax, index);
                  index = iMax;
                } else {
                  break;
                }
              }
            }

            function buildMaxHeap(array) {
              var i,
                iParent = Math.floor(array.length / 2) - 1;

              for (i = iParent; i >= 0; i--) {
                maxHeapify(array, i, array.length);
              }
            }

            function sort(array) {
              buildMaxHeap(array);

              for (var i = array.length - 1; i > 0; i--) {
                swap(array, 0, i);
                maxHeapify(array, 0, i);
              }
              return array;
            }

            return sort(result);
          }

          // 合并排序：将无序的数组 拆成N部分进行有序处理，然后合并；
          // 参考代码： https://gist.github.com/paullewis/1982121
          function sort9(array) {
            var result = array.slice(0);

            // 递归调用合并函数
            function sort(array) {
              var length = array.length,
                  mid    = Math.floor(length * 0.5),
                  left   = array.slice(0, mid),
                  right  = array.slice(mid, length);

              if(length === 1) {
                return array;
              }
              return merge(sort(left), sort(right));
            }

            // 合并 两有序的数组
            function merge(left, right) {
              var result = [];

              while(left.length || right.length) {

                if(left.length && right.length) {

                  if(left[0] < right[0]) {
                    result.push(left.shift());
                  } else {
                    result.push(right.shift());
                  }

                } else if (left.length) {
                  result.push(left.shift());
                } else {
                  result.push(right.shift());
                }
              }
              return result;
            }

            return sort(result);
          }

          // 随机从数组中获取 N个不重复的值, 默认从数组取一个值
          function ran1(array, n){
            var _result = [], _index = 0, _arrayTemp;
            // 防止原数组被改变
            _arrayTemp = array.slice(0); 
            if (array == null || array.length == 0 || array.length < n){
              return _result;
            }
            // 随机获取一个值
            if (n == null){
              _index = Math.floor(Math.random() * array.length);
              _result.push(array[_index]);
            }else{
              // 随机获取N个值
              for (var i = 0; i < n; i++){
                _index = Math.floor(Math.random() * _arrayTemp.length);
                _result.push(_arrayTemp[_index]);
                // 删除该元素
                _arrayTemp.splice(_index, 1);
              }
            }
            return _result;
          }
          // 随机打乱数组，使数组内元素与原来位置完全不同
          function ran2(array){
            var array_tmp = [], i , j, len, new_a = [], a_obj;
            
            // 添加数组原位置标志位
            for (i = 0, len = array.length; i < len; i++) {
              a_obj = {
                'key': i,
                'val': array[i]
              };
              array_tmp.push(a_obj);
            }

            for (i = 0, len = array.length; i < len; i++) {
              j = ranCount(array_tmp.length);
              // 如下标位置与原值重复，重新随机
              while ( i === array_tmp[j].key ) {
                j = ranCount(array_tmp.length);
              }
              new_a.push( array_tmp[j].val );
              // 删除数组
              array_tmp.splice(j,1);
            }

            // 获得给定数字的随机数, 出错返回-1
            function ranCount(n){
              var result = parseInt(n, 10);
              if ( isNaN(result) ) {
                result = -1;
              }
              result = Math.floor(Math.random() * result)
              return result;
            }

            return new_a;
          }

          // 从指定范围内，随机获取N个值的数组
          function ran3(){
            var result = [], SCOPE_NO = 100, COUNT = 10;

            result = getRandomNo(SCOPE_NO, COUNT);
            function getRandomNo(scope_no, count){
              var i, s_n, ran_n, _result = [];
              
              s_n = parseInt(scope_no, 10);
              for (i = 0; i < count; i++) {
                ran_n = Math.floor(Math.random() * s_n);
                _result.push(ran_n);
              }
              return _result;
            }

            return result;
          }
        </script>

    </body>
</html>